package com.mars.filter;

import com.google.common.base.Splitter;
import com.google.common.collect.Sets;
import com.mars.common.ApplicationContextHelper;
import com.mars.common.JsonData;
import com.mars.common.RequestHolder;
import com.mars.pojo.SysUser;
import com.mars.service.SysCoreService;
import com.mars.util.JsonMapper;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 权限拦截
 * @author MARS
 * @date 2018/2/11
 */
@Slf4j
public class AclControlFilter implements Filter{
    private static Set<String> exclusionUrlSet = Sets.newConcurrentHashSet();
    // 无权限访问页面
    private final static String noAuthUrl = "/permission/sys/user/noAuth.page";
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 定义白名单，排除的url,读取配置文件中需要过滤的url
        String exclusionUrls =  filterConfig.getInitParameter("exclusionUrls");
        // 获取string中每一个url
        List<String> exclusionUrlList = Splitter.on(",").trimResults().omitEmptyStrings().splitToList(exclusionUrls);
        exclusionUrlSet = Sets.newConcurrentHashSet(exclusionUrlList);
        // 需要将无权限访问的url也加入白名单，否则会进入无限循环
        exclusionUrlSet.add(noAuthUrl);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        // 白名单处理，获取请求
        String servletPath = request.getServletPath();
        Map requestMap = request.getParameterMap();
        if (exclusionUrlSet.contains(servletPath)) {
            filterChain.doFilter(request,response);
            return ;
        }

        // 黑名单处理
        // 情况一：用户值为空时
        SysUser sysUser = RequestHolder.getCurrentUser();
        if (sysUser == null ) {
            log.info("someone visit {},but no login,parameter:{}",servletPath, JsonMapper.obj2String(requestMap));
            noAuth(request,response);
            return;
        }

        // 情况二
        SysCoreService sysCoreService = ApplicationContextHelper.popBean(SysCoreService.class);
        if (!sysCoreService.hasUrlAcl(servletPath)) {
            log.info("{} visit {} ,but no login,parameter:{}",JsonMapper.obj2String(sysUser),servletPath, JsonMapper.obj2String(requestMap));
            noAuth(request,response);
            return;
        }

        filterChain.doFilter(servletRequest,servletResponse);
        return;
    }

    // 无权限访问的方法
    private  void noAuth( HttpServletRequest request,HttpServletResponse response ) throws IOException {
        // 获取url，来判断是page请求还是json请求
        String servletPath = request.getServletPath();
        if (servletPath.endsWith(".json")) {
            JsonData jsonData = JsonData.fail("没有访问权限，如需要访问，请联系管理员");
            // 将信息回显到页面
            // 定义响应头
            response.setHeader("Content-Type","application/json"); // 保证返回值是json结构
            response.getWriter().print(JsonMapper.obj2String(jsonData));
        } else {
            // 无权限访问的跳转
            clientRedirect(noAuthUrl,response);
            return ;
        }
    }

    //客户端连接
    private void clientRedirect(String url,HttpServletResponse response ) throws IOException{
        response.setHeader("Content-Type","text/html"); // 保证返回值是json结构
        response.getWriter().print("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
                + "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" + "<head>\n" + "<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\"/>\n"
                + "<title>跳转中...</title>\n" + "</head>\n" + "<body>\n" + "跳转中，请稍候...\n" + "<script type=\"text/javascript\">//<![CDATA[\n"
                + "window.location.href='" + url + "?ret='+encodeURIComponent(window.location.href);\n" + "//]]></script>\n" + "</body>\n" + "</html>\n");
    }
    @Override
    public void destroy() {

    }
}
